NewtRTFM: Case Study of a Runaway Newton Application
Sandeep Shah
K2 Consultants, Inc.
sandeep@zk3.dec.com

THIS ARTICLE WAS FIRST PUBLISHED IN PDA DEVELOPERS (FORMERLY PIE DEVELOPERS)
MAGAZINE. COPYRIGHT (C) 1994 BY CREATIVE DIGITAL SYSTEMS. ALL RIGHTS RESERVED.
CONTACT CREATIVE DIGITAL SYSTEMS AT CDS@NETCOM.COM FOR MORE INFORMATION. 

NewtRTFM is a Newton-resident portable reference for the Newton developers.
You may ask: why do I care? (Translation: why isn't it in the ad pages that I
can conveniently skip?) A fair question. A discussion about why I decided to
develop it and how I went about doing it can induce important lessons about
the stages of the design and implementation of a large PDA application.
Hopefully, my replay of the (loud) thinking process will help you see a few
parallels in the nutty problems you are trying to crack yourself.

HOW IT ALL STARTED 
Since August 1993, Newton pioneers have had an interesting love-hate
relationship with Newton Programming. I am talking about the Newton Toolkit
(NTK). It was clear that the Newton had potential, and it was also clear that
the development environment would have to mature, especially the alpha
documentation that accompanied the beta software.
	The following problems hindered the learning process in the first few
months:

* missing or misleading information about functions, protos, classes,
behavior and other NewtonScript constructs;
* inconsistencies in function names;
* confusion about choosing methods instead of global functions;
* some not-so-obvious bugs in the early incarnations of the ROMs and
Platform files;
* no effective mechanism to print and study program listings.

In spite of the furious efforts by PIE DTS to answer questions through Q&As
and the net, the basic task of pulling it all together remained a daunting
one.
	This is where NewtRTFM enters. I wanted to have a single source
documentation that would be as portable as the Newton itself. That way I
could convert a little bit of spare time at the oddest of places into a
productive time to work on my favorite Newton project.
	Every developer knows how precious desktop screen real estate is when you
are in the middle of development. An electronic reference on the host would
be a bit inconvenient, disorienting and intrusive. Putting the reference on
the Newton, however, seemed like a good solution - when you are busy using
the Mac keyboard and wondering about the most appropriate function to use,
your Newton is just sitting there. Even when you're not near your development
environment, a Newton-based reference can still be useful.

BASIC DESIGN DECISIONS
Being from the Unix world, I have a strong attachment to the man pages that
provide on-line documentation about commands, system calls, arguments, return
values and other essential topics. I decided that this approach, coupled with
the combining of related topics into various categories, could make the whole
application tremendously useful for developers from beginning to expert
level. 
	The next important decision was deciding what information to include. In
order to be useful to a programmer NewtRTFM had to include all functions,
methods, protos, view classes, behavior slots and so on. This had a direct
bearing on the navigational structure. While it's easier to enter a name on a
keyboard-based machine, typing a name on a Newton is hardly an effective way
to look up a topic. (Letting a user say "show SendRemoteControlCode" through
the note pad can be a cute demo, a la "fax Bob," but it's not really
convenient). Besides, we need to consider the cases where a topic name is
known, partially known or totally unknown.
	Taking a cue from indices (as opposed to tables of content), I decided it
was easiest to split the name space by the first letter of each topic name.
Another way to organize that information would be to filter it by various
categories, such as "System Messages." The important lesson here is to
provide fast paths without relying too much on the information that needs to
be written or typed in.
	Next problem was the content within these topics. I decided that the
content should be minimal - a lot of verbiage would mean a lot of storage
which would render the project practically impossible. Also, it would make it
much harder to locate needed information quickly. (A serious modern-day
problem is not one of no information, but of too much information).
	 I decided to compartmentalize the information for every topic so you
could quickly zero in on the needed information. For example, you might know
that the Array() function creates an array, but you need to know the type and
the order of each argument. On the other hand you may need to brush up on
FindStringInFrame() by reading a brief description. The other two useful
items I decided to include were a sensible example and personal annotation. 

An Application, not a Book
Let me take a quick detour to list my reasons for not doing a Newton
book.	
	At  first glance, this may seem like an ideal situation to create a
Newton Book. However, after having worked with various hypertext-based
programming references as a user, I decided against it for a few reasons:

* Linked topics and navigation have a disorienting effect on the reader
because of the lack of a relative context and locality. 
* When the task is for reference, you are interested in zeroing on the
needed information quickly.
* The size of the book would be very large. As you see later, some of the
tricks I used to save space may not lend themselves well to the Bookmaker
format.

PUTTING IT ALL TOGETHER
Enough rambling about the preparation. Let's delve into the interface I came
up with (see Figure 1). Note that after going through multiple iterative
experiments, I decided that the most effective interface was to have a
wallpaper-style interface (much like the built-in paper Roll), allowing
enough hooks to let you do your routine tasks.
	With this interface, the main portion of the screen shows the details for
a particular topic. There are four tabs on the right-hand side of the main
view - info, args, show and note - for viewing a description, an argument
summary, an example and your personal notations. There are also four primary
navigation aids:

* the alphabetic palette at the bottom lets you selecting a topic
alphabetically;
* the All button lets you select a subset of topics by category;
* the GoTo button lets you look up a topic by partial string match; and
* the arrows at the top of the screen let you sequence through the current
set of topics.

These navigation aids satisfied my need to find any topic or detail quickly.
	I first implemented a small floating alphabet that showed "A" through "Z"
like the Name application. If you tapped on a letter it displayed a popup of
all the topics starting with that letter. Selecting an item switched to that
topic. This approach had two problems:

* A child view can't be bigger than its parent view - I had to change the
alphabet's viewBounds with SetValue() just before showing this view. This was
slow and distracting.
* I realized that any reference session consists of looking up multiple
topics - the topic information stays on the screen all the time. The alphabet
palette end up being an annoying distraction. 

MAJOR CHALLENGES
Now lets look at the serious challenges and what I tried to counter them. 

Soup or Not?
NewtRTFM's data is primarily read-only. Looking at soup overhead and
performance, I decided to put the data within the package itself. I
experimented with some homegrown indexing that is easy to implement in
NewtonScript because of the flexibility of frames and arrays. (Most of my
experiments are similar in spirit, although not as elegantly executed, to
those outlined in "Lost In Space" by Mike Engber in PIE Developers 2.3). I
chose a hybrid method using a "frame-of-array-of-frames" with "meta-indexing"
that is hard coded to my needs.

A Special Popup
One of the important navigational features is the alphabetic palette that
lets you see a popup of all topics that begin with the letter you tap. A
popup is simple to do with the DoPopup() function. However, it does not
handle the case where the items span multiple screens. I had to create a
multi-screen popup of my own (see Figure 2). 
	I used a view based on clPickView with a method :DoPopup that takes the
same arguments as DoPopup() and add the meta items [--Next--] and [--Prev--] in
the subset of the large list. With a little logic in the pickActionScript to
detect if one of these meta items is tapped. 
	(Due to many requests, I am in the process of finalizing this popup as a
public domain user proto that can be used by anyone who is interested).

Runtime vs. Compile-time Trade-offs
After a brief flirtation with building the indexing structures in the
InstallScript, I stumbled upon the wonderful AfterScript. This is where most
of my raw data massaging occurs. Whatever you do in an InstallScript has
runtime implications (both time spent while installing and resetting the
Newton, as well as the RAM used). It's better to do those things that are
known at build time using an AfterScript. Note that most of the data
management and utility functions and the NewtonScript language constructs are
available in the NTK environment and can be leveraged in an AfterScript.
Also, it's possible to provide cross references to objects that reside on
your built package. (The next section of this article shows another possible
use of AfterScripts). 
	As an example, if you have some data under development, and you want to
select only certain data on the basis of some compile-time constant, you can
use an AfterScript in the template that contains the selection information. I
use this technique to compile the project for a demo version of NewtRTFM (as
well as for a quick compile) by filtering out most of the data while building
the project.	
	
// The following file contains data in a large 
// frame with one slot for each letter of the 
// alphabet. For each alphabet, there is an array 
// of frames, one frame for each entry
//
// Load command will have this large frame in 
// allData
//
Load (HOME & "allData.f");

//
// This is the AfterScript for the base view
// Note that this is not a func, just a compound
// statement
//
AfterScript: 
	begin
		// Iterate over all "letters" to filter data
 	foreach alphaSym in 
		['a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'k,
		'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u,
		'v, 'w] do
 	begin
		if (allData.(alphaSym)) then 
		begin
			// "print" is useful for printing the 
			// compile time stuff to the inspector! 
			print("Slot" && alphaSym && "present")	
 			abc := []; // none to start with
 			foreach item in allDope.(alphaSym) do
 			begin 	
 				// now decide if we want this or not
				// 'kHasStuff is another script in the
				// Project Data that returns TRUE if 
				// this item is to be included, NIL 
				// otherwise
 				if (Call kHasStuff with (alphaSym, item)) then
 				begin
 					AddArraySlot(abc, item);
 				end;		 
 			end; // foreach item
 			// replace the slot
 			allDope.(alphaSym) := abc;
		end;	// if (allData.(alphaSym))
	end;	// foreach all symbols
end;	// End of AfterScript

Size
As I started stuffing NewtRTFM with its contents, the package started to
bloat, thanks to Unicode's two-byte characters. This is where the duo
StuffCString() and ExtractCString() came to my help. Since there is no
support for doing this directly through NTK (unless I surround all my string
with StuffCString), I resort to compressing the data using StuffCString in
the same AfterScript mentioned earlier. This almost halves the size of the
program, saving me almost 600K bytes in the final package. 
	Since C strings are reasonable candidates for compression, the final
package gets compressed to nearly half the size of the uncompressed data. In
my experiments, by keeping the package uncompressed, the speed improvement
came to just about 10%, hardly noticeable during the interaction. Keeping it
compressed clearly has much more merit.

Live Examples
Apple provides many samples illustrating various NewtonScript features. I
found it hard to try and refer to something effectively while developing an
application. For example I may want to check out some sample which includes
clParagraphView. Usually it's cumbersome in the middle of development to go
find the correct sample and extract the right feature from it. I wanted to
provide some sort of link to useful samples. 
	Since it is not practical to keep hundreds of full-fledged samples on a
Newton, I required an alternative. Once again keeping with the theme of
supplying just the needed information, I included an example that would
illustrate the exact usage for a topic. Most of the topics that have a visual
or sound effect are also live, meaning they execute automatically when you go
to the show page. 
	For example if you are looking at building a view using
protoExpandoShell, wouldn't it be nice to see a sample that shows how to
create one? That's exactly what I wanted NewtRTFM to do. Go to the topic,
open the show page and you see an example, complete with protoTextExpando,
protoPhoneExpando and protoPhoneExpando children (see Figure 3). If you want
to see behind the curtains, just close the view and you find the NewtonScript
source code that shows you how it was done (see Figure 4). If you want to use
the text, there is a simple way to cut and paste it to the Inspector or to
ViewFrame. 

OTHER TASKS
Let's look at some of the other things you may need to do while developing an
application:

* open the standard Newton programs such as Names, Dates;
* open and close the Newton Toolkit slip,
* open other applications that are in the Extras drawer;
* open the application you're working on; or
* write notes.

The first task is easily handled, thanks to the Newton's fixed button bar. I
decided to include some shortcuts to make it easy to accomplish some of these
other tasks:
	The three "holes" on the left side of NewtRTFM's page are ideal
candidates for buttons that I can attach a function to:

* The top button launches the Toolkit. It's marked with "i" for Inspector.
* The bottom button ("a" for Applications) displays an alphabetical popup
list of all the programs in the Extras drawer. You can start any of those
applications from the popup.
* The remaining button ("e" for Extras and Express) provides an
interesting feature. Until you use the Extras button to launch an
application, this button brings up the Extras drawer. After you open an
application using the Applications button, this button acts as an Express
launcher for that program. Usually this is the program under development. 

INTERESTING BUGS
Well, are bugs ever really interesting? (Yes, but only in retrospect).
NewtonScript is deceptively simple. But bugs in large applications are hardly
that. Here is a quick list of what I faced and the reasons.

ClEditView
This one drove me nuts. Normally you wouldn't have a viewClickScript defined
for your view based on this class, because the default action is good enough.
But watch out if you have viewClickScripts in the parent hierarchy. If any of
them return TRUE, no matter how "distant" the grand parent is, the default
action for the clEditView is dropped. The end result is no ink or data in the
view. Although now it seems trivial and obvious, it wasn't, until I tried
everything else under the sun.

Sort()
I encountered another bug as a result of ignoring an important side effect of
the Sort() function. I used a simple-looking sort on the extras array in the
global heap:
	
	local apps := sort(extras, '|<str|, 'text);

so that I could iterate over each item to collect names to be displayed in a
popup. Can you see the problem here right away? If you don't, write "Sort is
destructive to the source array" 1000 times. The interesting thing was that
it wouldn't cause any problems until I tried to delete an application. Then
my Newton would freeze and the program would vanish, but it's memory would
never be released.

My Newton has Amnesia
I had a central script that I would call for every display event in a topic.
I found that every time I used it, there would be a leakage of frames heap
memory by up to 1K. I wrote a second application that used the data from
NewtRTFM and displayed it in a similar view hierarchy in a round-robin
fashion. No losses. I rewrote the script by splitting it into multiple pieces
(same code) and the leakage went away. The only reason I can suggest for the
leak was a large number of locals (around 21) that I was using in the
original script. There's no definite conclusion I can draw here, but I
learned to keep things small and simple.

CONCLUSION
This turned out to be a very interesting project, enriching my knowledge
about Newton development from all possible angles. Trying to come up with
samples that make sense and work interactively proved to be a challenging
task. No matter what, the Newton is a fun platform to work with and I hope
that NewtRTFM helps convey that image.
